/*
 *  nautilus-svn-browser.c - Subversion extension for Nautilus
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Author: Jack Xu Hong <jack.xu.hong@gmail.com>
 *
 */

#include <config.h>

#include <gtk/gtk.h>
#include <glade/glade.h>

#include <svn_client.h>
#include <svn_cmdline.h>
#include <svn_path.h>

#include "nautilus-svn.h"
#include "nautilus-svn-browser.h"

typedef struct {
	GtkWidget *window;

	GtkWidget *comboboxentry_url;
	GtkWidget *entry_url;
	GtkWidget *tree_view_folders;
	GtkTreeStore *tree_store_folders;
	GtkWidget *tree_view_contents;

	GtkWidget *button_refresh;
	GtkWidget *button_ok;
	GtkWidget *button_close;

	NautilusSvn *svn;
	const gchar *url;
	GtkTreeIter *current_node;

} NautilusSvnBrowser;


static svn_error_t*
list_func (void *baton,
           const char *path,
           const svn_dirent_t *dirent,
           const svn_lock_t *lock,
           const char *abs_path,
           apr_pool_t *pool)
{
	NautilusSvnBrowser *browser = (NautilusSvnBrowser *) baton;
	GtkTreeIter new_node;
	GtkTreeIter fake_child;

	if (strlen (path) == 0)
		return NULL;

	gtk_tree_store_append (browser->tree_store_folders, &new_node, browser->current_node);

	gtk_tree_store_set (browser->tree_store_folders, &new_node, 0, path, -1);

	// Add a fake child so that the node is displayed as expandable
	if (dirent->kind == svn_node_dir) {
		gtk_tree_store_append (browser->tree_store_folders, &fake_child, &new_node);
	}

	printf ("type = %d, author = %s, path = %s, absolute = %s\n", dirent->kind, dirent->last_author, path, abs_path);

	return NULL;
}

static void
list_url (NautilusSvnBrowser *browser, const gchar *new_url)
{
	svn_opt_revision_t revision;
	svn_opt_revision_t peg_revision;

	revision.kind = svn_opt_revision_head;
	peg_revision.kind = svn_opt_revision_unspecified;
	svn_error_t* err = svn_client_list(new_url,
	                                   &peg_revision,
	                                   &revision,
	                                   FALSE,
	                                   SVN_DIRENT_ALL,
	                                   FALSE,
	                                   list_func,
	                                   browser,
	                                   browser->svn->ctx,
	                                   browser->svn->pool);
	if (err != NULL) {
		printf(err->message);
		return;
	}
}

static void
nautilus_svn_browser_set_url (NautilusSvnBrowser *browser, const gchar *new_url)
{
	browser->url = svn_path_canonicalize (new_url, browser->svn->pool);

	list_url (browser, browser->url);
}

static void
tree_view_folders_row_expanded (GtkTreeView        *tree_view,
                                GtkTreeIter        *iter,
                                GtkTreePath        *path,
                                NautilusSvnBrowser *browser)
{
}

static gboolean
tree_view_folders_test_expand_row (GtkTreeView        *tree_view,
                                   GtkTreeIter        *iter,
                                   GtkTreePath        *path,
                                   NautilusSvnBrowser *browser)
{
	GtkTreeModel *model = GTK_TREE_MODEL (browser->tree_store_folders);
	gchar *node_name;
	gchar *url;
	GtkTreeIter child;
	gchar *child_name;

	if (gtk_tree_model_iter_children (model, &child, iter)) {
		gtk_tree_model_get (model, &child, 0, &child_name, -1);

		if (child_name) {
			// the node has been previously populated
			g_free (child_name);
			return FALSE;
		} else {
			// remove the fake child
			gtk_tree_store_remove (browser->tree_store_folders, &child);
		}
	}

	// Get the node name
	gtk_tree_model_get (model, iter, 0, &node_name, -1);

	// URL is created by concatenating the base url and the node name
	url = g_strconcat(browser->url, "/", node_name, NULL);

	printf ("new url: %s\n", url);

	browser->current_node = iter;
	list_url (browser, url);

	g_free (url);
	g_free (node_name);

	return FALSE;
}

static void
button_refresh_clicked_cb (GtkWidget          *widget,
                           NautilusSvnBrowser *browser)
{
	const gchar *url = gtk_entry_get_text (GTK_ENTRY (browser->entry_url));

	nautilus_svn_browser_set_url(browser, url);
}

static void
button_ok_clicked_cb (GtkWidget          *widget,
                      NautilusSvnBrowser *browser)
{
	gtk_widget_destroy (browser->window);
}

static void
button_close_clicked_cb (GtkWidget          *widget,
                         NautilusSvnBrowser *browser)
{
	gtk_widget_destroy (browser->window);
}

static void
destroy_cb (GtkWidget          *widget,
            NautilusSvnBrowser *browser)
{
	nautilus_svn_destroy (browser->svn);

	g_free (browser);
}

void
nautilus_svn_browser_show (GtkWidget   *parent,
                           const gchar *url)
{
	NautilusSvnBrowser *browser;
	GladeXML *xml;
	//GtkTreeViewColumn *col;
	GtkCellRenderer *renderer;

	browser = g_new0 (NautilusSvnBrowser, 1);
	browser->svn = nautilus_svn_init ();
	browser->url = NULL;

	xml = glade_xml_new (GLADEDIR "/nautilus-svn-browser.glade",
	                     NULL, NULL);
	browser->window = glade_xml_get_widget (xml, "dialog_browser");
	g_signal_connect (browser->window,
	                  "destroy",
	                  G_CALLBACK (destroy_cb),
	                  browser);

	browser->button_refresh = glade_xml_get_widget (xml, "button_refresh");
	g_signal_connect (browser->button_refresh,
	                  "clicked",
	                  G_CALLBACK (button_refresh_clicked_cb),
	                  browser);

	browser->button_ok = glade_xml_get_widget (xml, "button_ok");
	g_signal_connect (browser->button_ok,
	                  "clicked",
	                  G_CALLBACK (button_ok_clicked_cb),
	                  browser);

	browser->button_close = glade_xml_get_widget (xml, "button_close");
	g_signal_connect (browser->button_close,
	                  "clicked",
	                  G_CALLBACK (button_close_clicked_cb),
	                  browser);

	browser->comboboxentry_url = glade_xml_get_widget (xml, "comboboxentry_url");
	browser->entry_url = glade_xml_get_widget (xml, "entry_url");

	browser->tree_view_folders = glade_xml_get_widget (xml, "treeview_folders");
	g_signal_connect (browser->tree_view_folders,
	                  "row-expanded",
	                  G_CALLBACK (tree_view_folders_row_expanded),
	                  browser);
	g_signal_connect (browser->tree_view_folders,
	                  "test-expand-row",
	                  G_CALLBACK (tree_view_folders_test_expand_row),
	                  browser);

	renderer = gtk_cell_renderer_text_new();
	gtk_tree_view_insert_column_with_attributes(
			GTK_TREE_VIEW (browser->tree_view_folders),
			-1,
			"Path",
			renderer,
			"text", 0, NULL);

	browser->tree_store_folders = gtk_tree_store_new (1, G_TYPE_STRING, NULL);
	gtk_tree_view_set_model (GTK_TREE_VIEW (browser->tree_view_folders),
			GTK_TREE_MODEL (browser->tree_store_folders));
	g_object_unref (browser->tree_store_folders);


	if (url)
	{
		gtk_entry_set_text (GTK_ENTRY (browser->entry_url), url);

		nautilus_svn_browser_set_url(browser, url);
	}

	g_object_unref(xml);

	if (GTK_IS_WIDGET(parent))
		gtk_widget_set_parent(browser->window, parent);

	gtk_widget_show (browser->window);
}
